<script setup lang="ts">
import { defineExpose, reactive, ref } from 'vue'
import { getSliderCaptcha, verifyCaptcha } from '@/api/modules/system/admin/captcha'

// 事件定义
const emit = defineEmits<{
  success: []
  close: []
}>()

// 引用
const popup = ref()

// 响应式数据
const captchaData = reactive({
  originalImage: '',
  jigsawImage: '',
  token: '',
  secretKey: '',
})

const sliderLeft = ref(0)
const jigsawLeft = ref(0)
const sliderText = ref('请拖动滑块完成验证')
const isDragging = ref(false)
const startX = ref(0)
const maxSliderLeft = ref(280) // 滑块轨道最大宽度

// 获取验证码
async function getCaptcha() {
  try {
    const { data } = await getSliderCaptcha({ captchaType: 'blockPuzzle' })
    if (data.success) {
      captchaData.originalImage = `data:image/png;base64,${data.repData.originalImageBase64}`
      captchaData.jigsawImage = `data:image/png;base64,${data.repData.jigsawImageBase64}`
      captchaData.token = data.repData.token
      captchaData.secretKey = data.repData.secretKey
    }
  }
  catch (error) {
    console.error('获取验证码失败:', error)
    uni.showToast({
      title: '获取验证码失败',
      icon: 'none',
    })
  }
}

// 显示验证码
function show() {
  popup.value?.open()
  getCaptcha()
}

// 关闭验证码
function closeCaptcha() {
  popup.value?.close()
  resetSlider()
  emit('close')
}

// 重置滑块
function resetSlider() {
  sliderLeft.value = 0
  jigsawLeft.value = 0
  sliderText.value = '请拖动滑块完成验证'
  isDragging.value = false
}

// 触摸开始
function onTouchStart(e: TouchEvent) {
  isDragging.value = true
  startX.value = e.touches[0].clientX - sliderLeft.value
}

// 触摸移动
function onTouchMove(e: TouchEvent) {
  if (!isDragging.value)
    return

  e.preventDefault()
  const currentX = e.touches[0].clientX - startX.value

  if (currentX >= 0 && currentX <= maxSliderLeft.value) {
    sliderLeft.value = currentX
    jigsawLeft.value = currentX

    // 更新提示文字
    const progress = Math.round((currentX / maxSliderLeft.value) * 100)
    sliderText.value = `${progress}%`
  }
}

// 触摸结束
async function onTouchEnd() {
  if (!isDragging.value)
    return

  isDragging.value = false

  try {
    // 验证滑块位置
    const pointJson = JSON.stringify({
      x: jigsawLeft.value,
      y: 0,
    })

    const { data } = await verifyCaptcha({
      captchaType: 'blockPuzzle',
      pointJson,
      token: captchaData.token,
    })

    if (data.success) {
      sliderText.value = '验证成功'
      uni.showToast({
        title: '验证成功',
        icon: 'success',
      })

      setTimeout(() => {
        closeCaptcha()
        emit('success')
      }, 1000)
    }
    else {
      sliderText.value = '验证失败，请重试'
      resetSlider()
      // 重新获取验证码
      setTimeout(() => {
        getCaptcha()
      }, 1000)
    }
  }
  catch (error) {
    console.error('验证失败:', error)
    sliderText.value = '验证失败，请重试'
    resetSlider()
    setTimeout(() => {
      getCaptcha()
    }, 1000)
  }
}

// 暴露方法
defineExpose({
  show,
})
</script>

<template>
  <view class="slider-captcha">
    <uni-popup ref="popup" type="center" background-color="#fff">
      <view class="captcha-container">
        <view class="captcha-header">
          <text class="title">
            安全验证
          </text>
          <text class="close" @click="closeCaptcha">
            ×
          </text>
        </view>

        <view class="captcha-content">
          <view class="captcha-images">
            <image
              v-if="captchaData.originalImage"
              :src="captchaData.originalImage"
              class="bg-image"
              mode="widthFix"
            />
            <image
              v-if="captchaData.jigsawImage"
              :src="captchaData.jigsawImage"
              class="jigsaw-image"
              :style="{ left: `${jigsawLeft}px` }"
              mode="widthFix"
            />
          </view>

          <view class="slider-track">
            <view class="slider-bg">
              <text class="slider-text">
                {{ sliderText }}
              </text>
            </view>
            <view
              class="slider-btn"
              :style="{ left: `${sliderLeft}px` }"
              @touchstart="onTouchStart"
              @touchmove="onTouchMove"
              @touchend="onTouchEnd"
            >
              <text class="slider-icon">
                →
              </text>
            </view>
          </view>
        </view>
      </view>
    </uni-popup>
  </view>
</template>

<style lang="scss" scoped>
.captcha-container {
  width: 400rpx;
  background: #fff;
  border-radius: 20rpx;
  overflow: hidden;
}

.captcha-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 30rpx 40rpx;
  border-bottom: 1rpx solid #eee;

  .title {
    font-size: 32rpx;
    font-weight: bold;
    color: #333;
  }

  .close {
    font-size: 40rpx;
    color: #999;
    width: 60rpx;
    height: 60rpx;
    text-align: center;
    line-height: 60rpx;
  }
}

.captcha-content {
  padding: 40rpx;
}

.captcha-images {
  position: relative;
  width: 320rpx;
  height: 160rpx;
  margin: 0 auto 40rpx;
  border: 1rpx solid #ddd;
  border-radius: 10rpx;
  overflow: hidden;

  .bg-image {
    width: 100%;
    height: 100%;
  }

  .jigsaw-image {
    position: absolute;
    top: 0;
    width: 80rpx;
    height: 80rpx;
    transition: none;
  }
}

.slider-track {
  position: relative;
  width: 320rpx;
  height: 80rpx;
  margin: 0 auto;

  .slider-bg {
    width: 100%;
    height: 100%;
    background: #f0f0f0;
    border-radius: 40rpx;
    display: flex;
    align-items: center;
    justify-content: center;

    .slider-text {
      font-size: 24rpx;
      color: #999;
    }
  }

  .slider-btn {
    position: absolute;
    top: 0;
    left: 0;
    width: 80rpx;
    height: 80rpx;
    background: #4caf50;
    border-radius: 40rpx;
    display: flex;
    align-items: center;
    justify-content: center;
    box-shadow: 0 4rpx 8rpx rgba(0, 0, 0, 0.2);
    cursor: pointer;

    .slider-icon {
      color: #fff;
      font-size: 32rpx;
      font-weight: bold;
    }
  }
}
</style>
